/*
 * Copyright 2014-2026 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wzq.util;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 * json工具类，使用<a href="http://jackson.codehaus.org/">jackson json</a>
 */
public class UtilJson {
	public static final ObjectMapper mapper = newObjectMapper(), webMapper = mapper;

	private static ObjectMapper newObjectMapper() {
		ObjectMapper result = new ObjectMapper();
		result.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		result.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
		result.setSerializationInclusion(Include.NON_NULL);
		result.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);	//不输出value=null的属性
		result.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);	//不知道的属性，不异常
		return result;
	}

	/**
	 * 转化为json串
	 * @param value
	 * @return value == null ? null :
	 */
	public static String writerWithDefaultPrettyPrinter(Object value) {
		try {
			return value == null ? null : mapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);
		} catch (IOException e) {
			throw new IllegalArgumentException(e); // TIP: 原则上，不对异常包装，这里为什么要包装？因为正常情况不会发生IOException
		}
	}
	
	/**
	 * 转化为json bytes
	 * @param value
	 * @return value == null ? null :
	 */
	public static byte[] writeValueAsBytes(Object value) {
		try {
			return value == null ? null : mapper.writeValueAsBytes(value);
		} catch (IOException e) {
			throw new IllegalArgumentException(e); // TIP: 原则上，不对异常包装，这里为什么要包装？因为正常情况不会发生IOException
		}
	}
	
	/**
	 * 转化为json串
	 * @param value
	 * @return value == null ? null :
	 */
	public static String writeValueAsString(Object value) {
		try {
			return value == null ? null : mapper.writeValueAsString(value);
		} catch (IOException e) {
			throw new IllegalArgumentException(e); // TIP: 原则上，不对异常包装，这里为什么要包装？因为正常情况不会发生IOException
		}
	}

	/** 对象转换为map，如果是字符串，先转成json对象再转为map */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> toMap(Object value) throws IllegalArgumentException {
		return convertValue(value, Map.class);
	}
	
	/** 读取为List或者Map */
	@SuppressWarnings("unchecked")
	public static <T> T readValue(String content) {
		if (content == null || content.isEmpty()) return null;
		
		char ch = content.charAt(0);
		try {
			if (ch == '[') return (T) mapper.readValue(content, List.class);
			return (T) mapper.readValue(content, Map.class);
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}

	public static <T> T readValue(String content, Class<T> type) {
		if (content == null || content.isEmpty()) return null;
		try {
			return mapper.readValue(content, type);
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}
	public static <T> T readValue(byte[] content, Class<T> type) {
		if (content == null) return null;
		try {
			return mapper.readValue(content, type);
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}
	
	@SuppressWarnings("rawtypes")
	public static <T> T readMap(String content, Class<? extends Map> mapClass, Class<?> keyClass, Class<?> valueClass) {
		if (content == null) return null;
		try {
			return mapper.readValue(content, mapper.getTypeFactory().constructMapType(mapClass, keyClass, valueClass));
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}
	@SuppressWarnings("rawtypes")
	public static <T> T readCollection(String content, Class<? extends Collection> collectionClass, Class<?> elementClass) {
		if (content == null) return null;
		try {
			return mapper.readValue(content, mapper.getTypeFactory().constructCollectionType(collectionClass, elementClass));
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}
	public static <T> List<T> readListValue(String content, Class<T> elementClass) {
		if (content == null || content.isEmpty()) return null;
		try {
			return mapper.readValue(content, mapper.getTypeFactory().constructCollectionType(List.class, elementClass));
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}
	public static <T> T[] readArrayValue(String content, Class<T> elementClass) {
		if (content == null || content.isEmpty()) return null;
		try {
			return mapper.readValue(content, mapper.getTypeFactory().constructArrayType(elementClass));
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}
	
	/**
	 * 转换为目标类，如果value是字符串，将被认为是json串<br>
	 * 所以特别注意：'"abc"'是json字符串，目标类型是String时，转换结果为'abc'而不是'"abc"'<br>
	 * @param value
	 * @param clazz
	 * @return
	 * @throws IllegalArgumentException
	 */
	public static <T> T convertValue(Object value, Class<T> clazz) throws IllegalArgumentException {
		if (value == null) return null;
		try {
			if (value instanceof String) {
				if (!String.class.equals(clazz) && ((String) value).isEmpty()) return null;
				if (String.class.equals(clazz) && ((String) value).isEmpty()) return (T)value;
				value = mapper.readTree((String) value);
			}
			return mapper.convertValue(value, clazz);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
	}

	public static <T> T getCollectionType(String json, TypeReference<T> typeRef) {
		if (json == null || json.isEmpty()) return null;
		try {
			return  mapper.readValue(json, typeRef);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
	}
	
	/**
	 * 范型readValue
	 * json ==> Pager&lt;MyBean&gt;: readValue(json, Pager.class, MyBean.class)<br>
	 * json ==> List<Set<Integer>>: readValue(json, List.class, Integer.class)<br>
	 */
	public static <T> T readValue(String json, Class<?> parametrized, Class<?> parametersFor, Class<?>... parameterClasses) {
		if (json == null) return null;
		
		JavaType type;
		if (parameterClasses == null || parameterClasses.length == 0) {
			type = mapper.getTypeFactory().constructParametrizedType(parametrized, parametrized, parametersFor);
		} else {
			type = mapper.getTypeFactory().constructParametrizedType(parametrized, parametersFor, parameterClasses);
		}
		
		try {
			return mapper.readValue(json, type);
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}
}
